/**
 * 对象模块 - 借鉴Lodash的对象处理理念
 * 提供各种对象操作和处理功能
 */

/**
 * 检查是否为对象
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为对象
 */
export function isObject(value) {
  return typeof value === 'object' && value !== null && !Array.isArray(value);
}

/**
 * 检查是否为纯对象
 * @param {any} value 要检查的值
 * @returns {boolean} 是否为纯对象
 */
export function isPlainObject(value) {
  if (!isObject(value)) return false;

  if (Object.getPrototypeOf(value) === null) return true;

  let proto = value;
  while (Object.getPrototypeOf(proto) !== null) {
    proto = Object.getPrototypeOf(proto);
  }

  return Object.getPrototypeOf(value) === proto;
}

/**
 * 深度克隆对象
 * @param {any} obj 要克隆的对象
 * @returns {any} 克隆后的对象
 */
export function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') return obj;
  if (obj instanceof Date) return new Date(obj.getTime());
  if (obj instanceof RegExp) return new RegExp(obj);
  if (obj instanceof Array) return obj.map(item => deepClone(item));

  if (typeof obj === 'object') {
    const cloned = {};
    Object.keys(obj).forEach(key => {
      cloned[key] = deepClone(obj[key]);
    });
    return cloned;
  }

  return obj;
}

/**
 * 克隆对象（深克隆）
 * @param {any} obj 要克隆的对象
 * @returns {any} 克隆后的对象
 */
export function clone(obj) {
  return deepClone(obj);
}

/**
 * 浅克隆对象
 * @param {any} obj 要克隆的对象
 * @returns {any} 克隆后的对象
 */
export function shallowClone(obj) {
  if (obj === null || typeof obj !== 'object') return obj;
  if (obj instanceof Array) return [...obj];
  if (typeof obj === 'object') return { ...obj };
  return obj;
}

/**
 * 合并对象
 * @param {Object} target 目标对象
 * @param {...Object} sources 源对象
 * @returns {Object} 合并后的对象
 */
export function merge(target, ...sources) {
  if (!isObject(target)) return {};

  sources.forEach(source => {
    if (isObject(source)) {
      Object.keys(source).forEach(key => {
        if (isObject(source[key]) && isObject(target[key])) {
          target[key] = merge(target[key], source[key]);
        } else {
          target[key] = source[key];
        }
      });
    }
  });

  return target;
}

/**
 * 深度合并对象
 * @param {...Object} objects 要合并的对象
 * @returns {Object} 合并后的新对象
 */
export function deepMerge(...objects) {
  const result = {};

  objects.forEach(obj => {
    if (isObject(obj)) {
      Object.keys(obj).forEach(key => {
        if (isObject(obj[key]) && isObject(result[key])) {
          result[key] = deepMerge(result[key], obj[key]);
        } else {
          result[key] = deepClone(obj[key]);
        }
      });
    }
  });

  return result;
}

/**
 * 解析路径为键数组，支持数组索引
 * @param {string} path 路径字符串
 * @returns {string[]} 键数组
 */
function parsePath(path) {
  const keys = [];
  let current = '';
  let i = 0;

  while (i < path.length) {
    const char = path[i];

    if (char === '.') {
      if (current) {
        keys.push(current);
        current = '';
      }
    } else if (char === '[') {
      if (current) {
        keys.push(current);
        current = '';
      }
      // 找到对应的 ]
      i++;
      while (i < path.length && path[i] !== ']') {
        current += path[i];
        i++;
      }
      if (current) {
        keys.push(current);
        current = '';
      }
    } else {
      current += char;
    }
    i++;
  }

  if (current) {
    keys.push(current);
  }

  return keys;
}

/**
 * 获取对象属性值
 * @param {Object} obj 对象
 * @param {string} path 属性路径
 * @param {any} defaultValue 默认值
 * @returns {any} 属性值
 */
export function get(obj, path, defaultValue) {
  if (!obj || typeof path !== 'string') return defaultValue;

  const keys = parsePath(path);
  let result = obj;

  for (const key of keys) {
    if (result === null || result === undefined) {
      return defaultValue;
    }

    // 检查数字索引
    if (Array.isArray(result) && /^\d+$/.test(key)) {
      const index = parseInt(key, 10);
      if (index >= result.length) {
        return defaultValue;
      }
      result = result[index];
    } else if (!(key in result)) {
      return defaultValue;
    } else {
      result = result[key];
    }
  }

  return result;
}

/**
 * 设置对象属性值
 * @param {Object} obj 对象
 * @param {string} path 属性路径
 * @param {any} value 值
 * @returns {Object} 对象本身
 */
export function set(obj, path, value) {
  if (!obj || typeof path !== 'string') return obj;

  const keys = parsePath(path);
  let current = obj;

  for (let i = 0; i < keys.length - 1; i++) {
    const key = keys[i];
    const nextKey = keys[i + 1];
    const isNextKeyIndex = /^\d+$/.test(nextKey);

    if (Array.isArray(current) && /^\d+$/.test(key)) {
      const index = parseInt(key, 10);
      // 扩展数组长度如果需要
      while (current.length <= index) {
        current.push(undefined);
      }
      if (!current[index]) {
        current[index] = isNextKeyIndex ? [] : {};
      }
      current = current[index];
    } else {
      if (!(key in current)) {
        current[key] = isNextKeyIndex ? [] : {};
      }
      current = current[key];
    }
  }

  const lastKey = keys[keys.length - 1];
  if (Array.isArray(current) && /^\d+$/.test(lastKey)) {
    const index = parseInt(lastKey, 10);
    // 扩展数组长度如果需要
    while (current.length <= index) {
      current.push(undefined);
    }
    current[index] = value;
  } else {
    current[lastKey] = value;
  }

  return obj;
}

/**
 * 检查对象是否有指定属性
 * @param {Object} obj 对象
 * @param {string} path 属性路径
 * @returns {boolean} 是否有属性
 */
export function has(obj, path) {
  if (!isObject(obj) || typeof path !== 'string') return false;

  const keys = path.split('.');
  let current = obj;

  for (const key of keys) {
    if (current === null || current === undefined || !(key in current)) {
      return false;
    }
    current = current[key];
  }

  return true;
}

/**
 * 删除对象属性
 * @param {Object} obj 对象
 * @param {string} path 属性路径
 * @returns {boolean} 是否删除成功
 */
export function unset(obj, path) {
  if (!isObject(obj) || typeof path !== 'string') return false;

  const keys = path.split('.');
  let current = obj;

  for (let i = 0; i < keys.length - 1; i++) {
    const key = keys[i];
    if (!(key in current) || !isObject(current[key])) {
      return false;
    }
    current = current[key];
  }

  const lastKey = keys[keys.length - 1];
  if (lastKey in current) {
    delete current[lastKey];
    return true;
  }

  return false;
}

/**
 * 获取对象的所有键
 * @param {Object} obj 对象
 * @returns {string[]} 键数组
 */
export function keys(obj) {
  if (!isObject(obj)) return [];
  return Object.keys(obj);
}

/**
 * 获取对象的所有值
 * @param {Object} obj 对象
 * @returns {any[]} 值数组
 */
export function values(obj) {
  if (!isObject(obj)) return [];
  return Object.values(obj);
}

/**
 * 获取对象的键值对
 * @param {Object} obj 对象
 * @returns {Array[]} 键值对数组
 */
export function entries(obj) {
  if (!isObject(obj)) return [];
  return Object.entries(obj);
}

/**
 * 从键值对创建对象
 * @param {Array[]} pairs 键值对数组
 * @returns {Object} 对象
 */
export function fromEntries(pairs) {
  if (!Array.isArray(pairs)) return {};

  const result = {};
  pairs.forEach(pair => {
    if (Array.isArray(pair) && pair.length >= 2) {
      result[pair[0]] = pair[1];
    }
  });
  return result;
}

/**
 * 选择对象的指定属性
 * @param {Object} obj 对象
 * @param {string[]} keys 要选择的键
 * @returns {Object} 新对象
 */
export function pick(obj, keys) {
  if (!isObject(obj) || !Array.isArray(keys)) return {};

  const result = {};
  keys.forEach(key => {
    if (key in obj) {
      result[key] = obj[key];
    }
  });
  return result;
}

/**
 * 排除对象的指定属性
 * @param {Object} obj 对象
 * @param {string[]} keys 要排除的键
 * @returns {Object} 新对象
 */
export function omit(obj, keys) {
  if (!isObject(obj)) return {};
  if (!Array.isArray(keys)) return { ...obj };

  const result = { ...obj };
  keys.forEach(key => {
    delete result[key];
  });
  return result;
}

/**
 * 转换对象的值
 * @param {Object} obj 对象
 * @param {Function} iteratee 转换函数
 * @returns {Object} 转换后的对象
 */
export function mapValues(obj, iteratee) {
  if (!isObject(obj) || typeof iteratee !== 'function') return {};

  const result = {};
  Object.keys(obj).forEach(key => {
    result[key] = iteratee(obj[key], key, obj);
  });
  return result;
}

/**
 * 转换对象的键
 * @param {Object} obj 对象
 * @param {Function} iteratee 转换函数
 * @returns {Object} 转换后的对象
 */
export function mapKeys(obj, iteratee) {
  if (!isObject(obj) || typeof iteratee !== 'function') return {};

  const result = {};
  Object.keys(obj).forEach(key => {
    const newKey = iteratee(key, obj[key], obj);
    result[newKey] = obj[key];
  });
  return result;
}

/**
 * 反转对象的键值
 * @param {Object} obj 对象
 * @returns {Object} 反转后的对象
 */
export function invert(obj) {
  if (!isObject(obj)) return {};

  const result = {};
  Object.keys(obj).forEach(key => {
    result[obj[key]] = key;
  });
  return result;
}

/**
 * 对象扁平化
 * @param {Object} obj 对象
 * @param {string} separator 分隔符
 * @returns {Object} 扁平化后的对象
 */
export function flatten(obj, separator = '.') {
  if (!isObject(obj)) return {};

  const result = {};

  function flattenHelper(current, prefix = '') {
    Object.keys(current).forEach(key => {
      const newKey = prefix ? `${prefix}${separator}${key}` : key;

      if (isObject(current[key])) {
        flattenHelper(current[key], newKey);
      } else {
        result[newKey] = current[key];
      }
    });
  }

  flattenHelper(obj);
  return result;
}

/**
 * 对象反扁平化
 * @param {Object} obj 扁平化的对象
 * @param {string} separator 分隔符
 * @returns {Object} 反扁平化后的对象
 */
export function unflatten(obj, separator = '.') {
  if (!isObject(obj)) return {};

  const result = {};

  Object.keys(obj).forEach(key => {
    set(result, key.replace(new RegExp(separator.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), '.'), obj[key]);
  });

  return result;
}

/**
 * 深度比较两个对象是否相等
 * @param {any} obj1 对象1
 * @param {any} obj2 对象2
 * @returns {boolean} 是否相等
 */
export function isEqual(obj1, obj2) {
  if (obj1 === obj2) return true;

  if (obj1 === null || obj2 === null || obj1 === undefined || obj2 === undefined) {
    return obj1 === obj2;
  }

  if (typeof obj1 !== typeof obj2) return false;

  if (typeof obj1 !== 'object') return obj1 === obj2;

  if (Array.isArray(obj1) !== Array.isArray(obj2)) return false;

  if (Array.isArray(obj1)) {
    if (obj1.length !== obj2.length) return false;
    return obj1.every((item, index) => isEqual(item, obj2[index]));
  }

  const keys1 = Object.keys(obj1);
  const keys2 = Object.keys(obj2);

  if (keys1.length !== keys2.length) return false;

  return keys1.every(key => keys2.includes(key) && isEqual(obj1[key], obj2[key]));
}

/**
 * 获取对象的大小（属性数量）
 * @param {Object} obj 对象
 * @returns {number} 大小
 */
export function size(obj) {
  if (!isObject(obj)) return 0;
  return Object.keys(obj).length;
}

/**
 * 检查对象是否为空
 * @param {Object} obj 对象
 * @returns {boolean} 是否为空
 */
export function isEmpty(obj) {
  if (obj === null || obj === undefined) return true;
  if (Array.isArray(obj) || typeof obj === 'string') return obj.length === 0;
  if (isObject(obj)) return Object.keys(obj).length === 0;
  return false;
}

/**
 * 移除对象中的假值
 * @param {Object} obj 对象
 * @returns {Object} 移除假值后的新对象
 */
export function compact(obj) {
  if (!isObject(obj)) return {};

  const result = {};
  Object.keys(obj).forEach(key => {
    if (obj[key]) {
      result[key] = obj[key];
    }
  });
  return result;
}

/**
 * 使用默认值填充对象
 * @param {Object} obj 目标对象
 * @param {...Object} sources 默认值对象
 * @returns {Object} 填充后的对象
 */
export function defaults(obj, ...sources) {
  if (!isObject(obj)) return {};

  const result = { ...obj };

  sources.forEach(source => {
    if (isObject(source)) {
      Object.keys(source).forEach(key => {
        if (!(key in result)) {
          result[key] = source[key];
        }
      });
    }
  });

  return result;
}

/**
 * 转换对象
 * @param {Object} obj 对象
 * @param {Function} iteratee 转换函数
 * @returns {Object} 转换后的对象
 */
export function transform(obj, iteratee) {
  if (!isObject(obj) || typeof iteratee !== 'function') return {};

  const result = {};
  Object.keys(obj).forEach(key => {
    iteratee(result, obj[key], key, obj);
  });
  return result;
}

// ========== Lodash风格的对象操作函数 ==========

/**
 * 按条件选择对象属性
 * @param {Object} obj 对象
 * @param {Function} predicate 条件函数
 * @returns {Object} 新对象
 */
export function pickBy(obj, predicate) {
  if (!isObject(obj) || typeof predicate !== 'function') return {};

  const result = {};
  Object.keys(obj).forEach(key => {
    if (predicate(obj[key], key)) {
      result[key] = obj[key];
    }
  });
  return result;
}

/**
 * 按条件排除对象属性
 * @param {Object} obj 对象
 * @param {Function} predicate 条件函数
 * @returns {Object} 新对象
 */
export function omitBy(obj, predicate) {
  if (!isObject(obj) || typeof predicate !== 'function') return { ...obj };

  const result = {};
  Object.keys(obj).forEach(key => {
    if (!predicate(obj[key], key)) {
      result[key] = obj[key];
    }
  });
  return result;
}

/**
 * 查找满足条件的键
 * @param {Object} obj 对象
 * @param {Function} predicate 条件函数
 * @returns {string|undefined} 键名
 */
export function findKey(obj, predicate) {
  if (!isObject(obj) || typeof predicate !== 'function') return undefined;

  for (const key of Object.keys(obj)) {
    if (predicate(obj[key], key, obj)) {
      return key;
    }
  }
  return undefined;
}

/**
 * 从右向左查找满足条件的键
 * @param {Object} obj 对象
 * @param {Function} predicate 条件函数
 * @returns {string|undefined} 键名
 */
export function findLastKey(obj, predicate) {
  if (!isObject(obj) || typeof predicate !== 'function') return undefined;

  const keys = Object.keys(obj);
  for (let i = keys.length - 1; i >= 0; i--) {
    const key = keys[i];
    if (predicate(obj[key], key, obj)) {
      return key;
    }
  }
  return undefined;
}

/**
 * 批量获取路径值
 * @param {Object} obj 对象
 * @param {...string} paths 路径数组
 * @returns {Array} 值数组
 */
export function at(obj, ...paths) {
  if (!obj) return [];

  return paths.map(path => get(obj, path));
}

/**
 * 分配对象属性（浅拷贝）
 * @param {Object} target 目标对象
 * @param {...Object} sources 源对象
 * @returns {Object} 目标对象
 */
export function assign(target, ...sources) {
  if (!target) return {};

  sources.forEach(source => {
    if (isObject(source) || Array.isArray(source)) {
      Object.keys(source).forEach(key => {
        target[key] = source[key];
      });
    }
  });

  return target;
}

/**
 * 分配对象属性（包括继承的属性）
 * @param {Object} target 目标对象
 * @param {...Object} sources 源对象
 * @returns {Object} 目标对象
 */
export function assignIn(target, ...sources) {
  if (!target) return {};

  sources.forEach(source => {
    if (source) {
      for (const key in source) {
        target[key] = source[key];
      }
    }
  });

  return target;
}

/**
 * extend别名（同assignIn）
 * @param {Object} target 目标对象
 * @param {...Object} sources 源对象
 * @returns {Object} 目标对象
 */
export function extend(target, ...sources) {
  return assignIn(target, ...sources);
}

/**
 * 自定义合并对象
 * @param {Object} target 目标对象
 * @param {...Object} sources 源对象和自定义函数
 * @returns {Object} 合并后的对象
 */
export function mergeWith(target, ...sources) {
  if (!isObject(target)) return {};

  // 最后一个参数可能是自定义函数
  const customizer = typeof sources[sources.length - 1] === 'function'
    ? sources.pop()
    : null;

  sources.forEach(source => {
    if (isObject(source)) {
      Object.keys(source).forEach(key => {
        if (customizer) {
          const result = customizer(target[key], source[key], key, target, source);
          if (result !== undefined) {
            target[key] = result;
          } else if (isObject(source[key]) && isObject(target[key])) {
            target[key] = mergeWith(target[key], source[key], customizer);
          } else {
            target[key] = source[key];
          }
        } else if (isObject(source[key]) && isObject(target[key])) {
          target[key] = merge(target[key], source[key]);
        } else {
          target[key] = source[key];
        }
      });
    }
  });

  return target;
}

/**
 * 深度设置默认值
 * @param {Object} obj 目标对象
 * @param {...Object} sources 默认值对象
 * @returns {Object} 填充后的对象
 */
export function defaultsDeep(obj, ...sources) {
  if (!isObject(obj)) return {};

  const result = { ...obj };

  function deepDefaults(target, source) {
    Object.keys(source).forEach(key => {
      if (!(key in target)) {
        target[key] = deepClone(source[key]);
      } else if (isObject(target[key]) && isObject(source[key])) {
        deepDefaults(target[key], source[key]);
      }
    });
  }

  sources.forEach(source => {
    if (isObject(source)) {
      deepDefaults(result, source);
    }
  });

  return result;
}

/**
 * 遍历对象自身和继承的属性
 * @param {Object} obj 对象
 * @param {Function} iteratee 迭代函数
 * @returns {Object} 对象本身
 */
export function forIn(obj, iteratee) {
  if (!obj || typeof iteratee !== 'function') return obj;

  for (const key in obj) {
    if (iteratee(obj[key], key, obj) === false) {
      break;
    }
  }

  return obj;
}

/**
 * 遍历对象自身的属性
 * @param {Object} obj 对象
 * @param {Function} iteratee 迭代函数
 * @returns {Object} 对象本身
 */
export function forOwn(obj, iteratee) {
  if (!isObject(obj) || typeof iteratee !== 'function') return obj;

  Object.keys(obj).forEach(key => {
    iteratee(obj[key], key, obj);
  });

  return obj;
}

/**
 * 调用对象方法
 * @param {Object} obj 对象
 * @param {string} path 方法路径
 * @param {...any} args 参数
 * @returns {any} 方法返回值
 */
export function invoke(obj, path, ...args) {
  if (!obj || typeof path !== 'string') return undefined;

  const method = get(obj, path);
  if (typeof method === 'function') {
    // 获取方法所在的对象作为this
    const parts = path.split('.');
    const context = parts.length > 1 ? get(obj, parts.slice(0, -1).join('.')) : obj;
    return method.apply(context, args);
  }

  return undefined;
}

/**
 * 获取对象的所有方法名
 * @param {Object} obj 对象
 * @returns {string[]} 方法名数组
 */
export function functions(obj) {
  if (!isObject(obj)) return [];

  return Object.keys(obj).filter(key => typeof obj[key] === 'function');
}

/**
 * 获取对象的所有方法名（包括继承的）
 * @param {Object} obj 对象
 * @returns {string[]} 方法名数组
 */
export function functionsIn(obj) {
  if (!obj) return [];

  const result = [];
  for (const key in obj) {
    if (typeof obj[key] === 'function') {
      result.push(key);
    }
  }
  return result;
}

/**
 * toPairs别名（同entries）
 * @param {Object} obj 对象
 * @returns {Array[]} 键值对数组
 */
export function toPairs(obj) {
  return entries(obj);
}

/**
 * fromPairs别名（已在fromEntries中实现）
 * @param {Array[]} pairs 键值对数组
 * @returns {Object} 对象
 */
export function fromPairs(pairs) {
  return fromEntries(pairs);
}

/**
 * 创建对象的路径值数组
 * @param {Object} obj 对象
 * @param {string} path 路径
 * @returns {any} 路径值或执行结果
 */
export function result(obj, path, defaultValue) {
  if (!obj || typeof path !== 'string') return defaultValue;

  const value = get(obj, path, defaultValue);
  return typeof value === 'function' ? value.call(obj) : value;
}

/**
 * 检查对象是否有自己的属性（不含继承）
 * @param {Object} obj 对象
 * @param {string} key 键名
 * @returns {boolean} 是否有属性
 */
export function hasOwn(obj, key) {
  if (!obj || typeof key !== 'string') return false;
  return Object.prototype.hasOwnProperty.call(obj, key);
}

/**
 * 检查对象是否有属性（含继承）
 * @param {Object} obj 对象
 * @param {string} key 键名
 * @returns {boolean} 是否有属性
 */
export function hasIn(obj, key) {
  if (!obj || typeof key !== 'string') return false;
  return key in obj;
}

/**
 * 创建对象的浅拷贝，只包含给定路径的属性
 * @param {Object} obj 对象
 * @param {string[]} paths 路径数组
 * @returns {Object} 新对象
 */
export function pickPaths(obj, paths) {
  if (!obj || !Array.isArray(paths)) return {};

  const result = {};
  paths.forEach(path => {
    const value = get(obj, path);
    if (value !== undefined) {
      set(result, path, value);
    }
  });
  return result;
}

/**
 * 创建对象的浅拷贝，排除给定路径的属性
 * @param {Object} obj 对象
 * @param {string[]} paths 路径数组
 * @returns {Object} 新对象
 */
export function omitPaths(obj, paths) {
  if (!obj) return {};

  const result = deepClone(obj);
  paths.forEach(path => {
    unset(result, path);
  });
  return result;
}

/**
 * 按键索引创建对象
 * @param {Array} arr 数组
 * @param {string|Function} key 键或函数
 * @returns {Object} 索引对象
 */
export function keyBy(arr, key) {
  if (!Array.isArray(arr)) return {};

  const result = {};
  arr.forEach(item => {
    const itemKey = typeof key === 'function' ? key(item) : item[key];
    result[itemKey] = item;
  });
  return result;
}

/**
 * 反转对象的键值（支持多个值映射到同一个键）
 * @param {Object} obj 对象
 * @returns {Object} 反转后的对象
 */
export function invertBy(obj, iteratee) {
  if (!isObject(obj)) return {};

  const result = {};
  const getKey = typeof iteratee === 'function' ? iteratee : (val) => val;

  Object.keys(obj).forEach(key => {
    const value = getKey(obj[key]);
    if (!result[value]) {
      result[value] = [];
    }
    result[value].push(key);
  });

  return result;
}
